package com.bandi.tharshesnows;

import java.util.ArrayList;
import java.util.List;

import com.bandi.tharshesnows.model.County;
import com.bandi.tharshesnows.model.Resort;
import com.bandi.tharshesnows.model.Skirun;
import com.bandi.tharshesnows.parser.RomaniaTuristicaParser2;
import com.bandi.tharshesnows.service.SkirunsManager;

public class SkirunsProvider {

  private static SkirunsProvider INSTANCE;

  private List<County> cache;
  private SkirunsManager skirunsService;
  private RomaniaTuristicaParser2 parser;

  private SkirunsProvider() {
    skirunsService = new SkirunsManager();
    parser = RomaniaTuristicaParser2.getParser();
  }

  public static SkirunsProvider getInstance() {
    if (INSTANCE == null) {
      INSTANCE = new SkirunsProvider();
    }
    return INSTANCE;
  }

  public void getCounty(long id, final GetDataCallback<County> skirunsProviderCallback) {
    if (cache != null) {
      for (County c : cache) {
        if (c.get_id() == id) {
          skirunsProviderCallback.onData(c);
          return;
        }
      }
    }
    else {
      skirunsService.getCounty(id, skirunsProviderCallback);
    }
  }

  public void getCounties(boolean update, final GetDataCallback<List<County>> skirunsProviderCallback) {
    final GetDataCallback<List<County>> persistenceCallback = new GetDataCallback<List<County>>() {

      @Override
      public void onError(Throwable t) {
        skirunsProviderCallback.onError(t);
      }

      @Override
      public void onData(List<County> data) {
        cache = data;
        skirunsProviderCallback.onData(cache);
      }
    };
    final GetDataCallback<ArrayList<County>> networkCallback = new GetDataCallback<ArrayList<County>>() {

      @Override
      public void onError(Throwable t) {
        skirunsProviderCallback.onError(t);
      }

      @Override
      public void onData(ArrayList<County> data) {
        skirunsService.saveCounties(data, persistenceCallback);
      }
    };
    if (update) {
      // get from net
      clearCache();
      parser.parseAllCounties(networkCallback);
    }
    else {
      // get from persistence
      if (cache != null) {
        skirunsProviderCallback.onData(cache);
        return;
      }
      skirunsService.getAllCounties(persistenceCallback);
    }
  }

  public void getSkirun(final long countyId, final long localityId, final long skirunId, final boolean update,
      final GetDataCallback<Skirun> skirunsCallback) {
    // get county
    GetDataCallback<County> getCountyCallback = new GetDataCallback<County>() {

      @Override
      public void onError(Throwable t) {
        skirunsCallback.onError(t);
      }

      @Override
      public void onData(County data) {
        for (Resort l : data.getResorts()) {
          if (l.get_id() == localityId) {
            for (Skirun s : l.getSkiruns()) {
              if (s.get_id() == skirunId) {
                updateSkirun(update, s, skirunsCallback);
                return;
              }
            }
          }
        }
      }
    };
    if (cache != null) {
      for (County c : cache) {
        if (c.get_id() == countyId) {
          for (Resort l : c.getResorts()) {
            if (l.get_id() == localityId) {
              for (Skirun s : l.getSkiruns()) {
                if (s.get_id() == skirunId) {
                  updateSkirun(update, s, skirunsCallback);
                  return;
                }
              }
            }
          }
        }
      }
    }
    else {
      skirunsService.getCounty(localityId, getCountyCallback);
    }
  }

  private void updateSkirun(boolean update, Skirun skirun, final GetDataCallback<Skirun> skirunsCallback) {
    if (!skirun.isDownloaded() || update) {
      // update from network
      GetDataCallback<Skirun> updateCallback = new GetDataCallback<Skirun>() {

        @Override
        public void onError(Throwable t) {
          skirunsCallback.onError(t);
        }

        @Override
        public void onData(Skirun data) {
          data.setDownloaded(true);
          skirunsService.updateSkirun(data, skirunsCallback);
        }
      };
      if (skirun.isDownloaded()) {
        parser.updateSkirun(skirun, updateCallback);
      }
      else {
        parser.getNewSkirun(skirun, updateCallback);
      }
    }
    else {
      // get from cache
      skirunsCallback.onData(skirun);
    }
  }

  public void clearCache() {
    cache = null;
  }

}
